/*
 * Apple System Management Control (SMC) Tool
 *
 * Copyright (C) 2011 Luca Capellini luca.capellini@gmail.com
 * Copyright (C) 2006 devnull 
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */


/*
 * User friendly version of the SMC tool by devnull.
 * Please note that in order to change the fans' speed you need
 * to get privileges. Typically you may call "sudo chown root:admin path_to_executable"
 * and then "sudo chmod 6665 path_to_executable".
 */

#ifndef __SMC_H__
#define __SMC_H__
#endif

#define VERSION               "0.1"

#define MAX_FANS              4
#define KERNEL_INDEX_SMC      2

#define SMC_CMD_READ_BYTES    5
#define SMC_CMD_WRITE_BYTES   6
#define SMC_CMD_READ_INDEX    8
#define SMC_CMD_READ_KEYINFO  9
#define SMC_CMD_READ_PLIMIT   11
#define SMC_CMD_READ_VERS     12

typedef struct {
    char                  major;
    char                  minor;
    char                  build;
    char                  reserved[1]; 
    UInt16                release;
} SMCKeyData_vers_t;

typedef struct {
    UInt16                version;
    UInt16                length;
    UInt32                cpuPLimit;
    UInt32                gpuPLimit;
    UInt32                memPLimit;
} SMCKeyData_pLimitData_t;

typedef struct {
    UInt32                dataSize;
    UInt32                dataType;
    char                  dataAttributes;
} SMCKeyData_keyInfo_t;

typedef char              SMCBytes_t[32]; 

typedef struct {
    UInt32                  key; 
    SMCKeyData_vers_t       vers; 
    SMCKeyData_pLimitData_t pLimitData;
    SMCKeyData_keyInfo_t    keyInfo;
    char                    result;
    char                    status;
    char                    data8;
    UInt32                  data32;
    SMCBytes_t              bytes;
} SMCKeyData_t;

typedef char              UInt32Char_t[5];

typedef struct {
    UInt32Char_t            key;
    UInt32                  dataSize;
    UInt32Char_t            dataType;
    SMCBytes_t              bytes;
} SMCVal_t;

typedef struct {
    UInt32Char_t            identifier;
    UInt32                  maxSpeed;
    UInt32                  minSpeed;
    UInt32                  safeSpeed;
} SMCFanInfo_t;

typedef SMCFanInfo_t    SMCFansInfo_t[MAX_FANS];

typedef struct {
    SMCFansInfo_t           fans;
    io_connect_t            conn;
    UInt32                  fansNum;
} SMCSetup_t;

/* Public functions. Have fun! */

/*
 * Standard initialization.
 */
unsigned int SMCInit();

/*
 * Returns the current temperature (thermal sensor: TC#D), or
 * -1 if the temperature could not be retrieved.
 */
float SMCGetTemp();

/*
 * Calls SMCSetFanSpeed(MAX_FANS, speed)
 */
unsigned int SMCSetFansSpeed(int speed);

/*
 * Sets the speed of a fan to the given value.
 * If MAX_FAN is passed, then all the fans will be set the
 * given speed - call SMCSetFansSpeed() in this case.
 * If the given speed is less than the minimum supported (safeSpeed), the fan
 * will be set to its minimum speed and similarly if the speed
 * exceed the maximum supported.
 */
unsigned int SMCSetFanSpeed(int fan_number, int speed);

enum {
    SMCMaxFanSpeed  = 0,
    SMCMinFanSpeed  = 1,
    SMCSafeFanSpeed = 2
};

unsigned int SMCGetMinMaxSpeed(int fan_number, int minOrMax);

/*
 * Closes everything up. It is very important you call it,
 * as will set the fans mode to automatic - system default.
 */
void SMCRelease();